package com.yupfeg.executor

import java.util.concurrent.ExecutorService

/**
 * 通用线程池提供类
 * - 收敛应用中线程池使用，使用统一的线程库，其他业务库通过设置`setExecutor`等方式使用指定线程池
 * @author yuPFeG
 * @date 2022/01/04
 */
object ExecutorProvider {

    private var mFactory : ExecutorFactory? = null

    /**
     * IO密集型线程池
     * - 通常用于占用时间短的任务，实际并发量很小的任务
     * */
    @JvmStatic
    val ioExecutor : ExecutorService
        get() {
            return mIoExecutor ?: synchronized(this){
                mIoExecutor ?: createIoExecutor().apply { mIoExecutor = this }
            }
        }

    @Volatile
    private var mIoExecutor : ExecutorService? = null

    /**
     * CPU密集型线程池
     * - 用于线程占用时间较长的任务
     * - 占据CPU的时间片过多的话会影响性能，需要控制最大并发，防止主线程的抢占的时间片减少
     * */
    @JvmStatic
    val cpuExecutor : ExecutorService
        get() {
            return mCpuExecutor?: synchronized(this){
                mCpuExecutor ?: createCpuExecutor().apply { mCpuExecutor = this }
            }
        }

    @Volatile
    private var mCpuExecutor : ExecutorService? = null

    /**
     * 准备线程池配置
     * - 只在需要修改线程池配置时才需要调用
     * - 只能在调用[ioExecutor]、[cpuExecutor]函数前调用一次修改线程配置，否则抛出异常
     * @param factory 线程池工厂类
     * @throws RuntimeException 重复设置线程池配置异常
     * */
    @JvmStatic
    @Throws(RuntimeException::class)
    fun prepare(factory: ExecutorFactory){
        if (mFactory!= null){
            throw RuntimeException("executor provider is already , can not prepare again")
        }
        mFactory = factory
    }

    /**
     * 创建IO密集型的线程池
     * */
    private fun createIoExecutor() : ExecutorService{
        initDefaultExecutorFactory()
        return mFactory!!.createIOThreadPool()
    }

    /**
     * 创建CPU密集型的线程池
     * */
    private fun createCpuExecutor() : ExecutorService{
        initDefaultExecutorFactory()
        return mFactory!!.createCPUThreadPool()
    }

    /**
     * 初始化默认配置的线程池工厂实例
     * */
    private fun initDefaultExecutorFactory(){
        mFactory?:run {
            mFactory = DefaultExecutorFactory()
        }
    }
}